<template>
  <div id="CesiumContainer">
    <div class="button">
      <!-- <el-button type="danger" round @click="loadSimple">Simple</el-button> -->
      <el-button type="danger" round @click="initCesium">初始化</el-button>
      <el-button type="danger" round @click="loadSatellites"
        >千帆卫星</el-button
      >
      <el-button type="danger" round @click="locateView">定位</el-button>
    </div>
  </div>
</template>

<script>
import * as Cesium from "cesium";
import "/node_modules/cesium/Build/Cesium/Widgets/widgets.css";
import * as dat from "dat.gui";

Cesium.Ion.defaultAccessToken =
  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJhOTM4NmM2ZC0yNzQ3LTRjYTQtYWMxZC00YjJlOWQ5ZGNjYTQiLCJpZCI6Mjc2NjA1LCJpYXQiOjE3Mzk3Nzk2NjJ9.a-ivPAeqR5CXISd0Y2Pm_lAp1q7fpLPc3a8NWLXvreA";

export default {
  data() {
    return {
      viewer: null,
      boatEntity: null,
      visibilityRange: 1500000, // 可见范围（1500km）
      satelliteEntities: [],
      intervalId: null,
      beamEntities: [], // 保存黄色波束实体
      redBeamEntities: [], // 保存红色波束实体
      currentSatelliteIndex: 0, // 当前卫星索引
      timer: 500, // 波束切换时间间隔（毫秒）
      boatParams: {
        longitude: 125,
        latitude: 30,
        height: 0,
        heading: 45,
        pitch: 0,
        roll: 0,
      },
      gui: null,
    };
  },
  mounted() {
    if (!this.viewer) {
      this.initCesium();
    }
  },
  beforeUnmount() {
    if (this.viewer && !this.viewer.isDestroyed()) {
      this.viewer.destroy();
      this.viewer = null;
    }
    if (this.intervalId) {
      clearInterval(this.intervalId);
    }
    if (this.gui) {
      this.gui.destroy();
    }
  },
  methods: {
    async initCesium() {
      if (this.viewer) {
        this.viewer.destroy();
        this.viewer = null;
        this.satelliteEntities = [];
        this.beamEntities = [];
        this.redBeamEntities = [];
        this.currentSatelliteIndex = 0;
      }
      try {
        this.viewer = new Cesium.Viewer("CesiumContainer", {
          shouldAnimate: true,
          timeline: true,
          animation: true,
          // globe: false
        });
        // const webKey = "ad3d69444931d48a86d0aa4c0d2f3dc9";
        const webKey = "	34a8d6c835f1003152c95e03cabc18be";
        this.viewer._cesiumWidget._creditContainer.style.display = "none"; //去掉左下角那个不可爱的图标
        // 影像底图
        /*

        this.viewer.imageryLayers.addImageryProvider(
          new Cesium.WebMapTileServiceImageryProvider({
            url:
              "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=" +
              webKey,
            layer: "tdtBasicLayer",
            style: "default",
            format: "image/jpeg",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: true,
            enableCache: true, // 启用缓存
          })
        );
        //影像注记
        this.viewer.imageryLayers.addImageryProvider(
          new Cesium.WebMapTileServiceImageryProvider({
            url:
              "http://t0.tianditu.com/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=" +
              webKey,
            layer: "tdtAnnoLayer",
            style: "default",
            format: "image/jpeg",
            tileMatrixSetID: "GoogleMapsCompatible",
            show: false,
            enableCache: true, // 启用缓存
          })
        );
        this.viewer.scene.globe.maximumScreenSpaceError = 1; // 默认值是 2，调低可以提高清晰度
        this.viewer.scene.globe.enableLighting = true;
        this.viewer.scene.logarithmicDepthBuffer = true;
        this.viewer.scene.fog.enabled = false; // 关闭雾效，避免模糊
        this.viewer.scene.globe.enableLighting = false; // 关闭动态光照，减少自动降级
        this.viewer.resolutionScale = 2.0; // 提高渲染分辨率
        
        */

        // const tileset = await Cesium.createGooglePhotorealistic3DTileset({
        //     // Only the Google Geocoder can be used with Google Photorealistic 3D Tiles.  Set the `geocode` property of the viewer constructor options to IonGeocodeProviderType.GOOGLE.
        //     onlyUsingWithGoogleGeocoder: true,
        // });
        // this.viewer.scene.primitives.add(tileset);

        this.viewer.camera.flyTo({
          destination: Cesium.Cartesian3.fromDegrees(110, 35, 20000000),
          duration: 3,
        });
        // 初始化时创建蓝色波束和红色波束实体
        this.createInitialBeams();
      } catch (error) {
        console.error("Cesium Viewer 初始化失败:", error);
      }
    },
    createInitialBeams() {
      // 创建蓝色波束实体（底面和侧面）
      const blueBeamEntity = this.createBeamEntity(Cesium.Color.BLUE);
      this.beamEntities.push(blueBeamEntity);

      // 创建红色波束实体（底面和侧面）
      const redBeamEntity = this.createBeamEntity(Cesium.Color.RED);
      this.redBeamEntities.push(redBeamEntity);
    },

    createBeamEntity(color) {
      // 创建底面实体
      const baseEntity = this.viewer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy([]),
          material: color.withAlpha(0.8),
          perPositionHeight: true,
        },
      });

      // 创建四个侧面实体
      const sideEntities = [
        this._createTriangleFace(color),
        this._createTriangleFace(color),
        this._createTriangleFace(color),
        this._createTriangleFace(color),
      ];

      // 返回底面和侧面实体
      return { baseEntity, sideEntities };
    },

    _createTriangleFace(color) {
      return this.viewer.entities.add({
        polygon: {
          hierarchy: new Cesium.PolygonHierarchy([]),
          material: color.withAlpha(0.8),
          perPositionHeight: true,
        },
      });
    },
    initGUI() {
      if (this.gui) {
        this.gui.destroy();
      }
      this.gui = new dat.GUI();
      this.gui.domElement.style.position = "absolute";
      this.gui.domElement.style.top = "10px";
      this.gui.domElement.style.right = "200px";
      this.gui.domElement.style.zIndex = 1000; // 确保 GUI 组件在其他元素之上
      this.gui
        .add(this.boatParams, "longitude", -180, 180)
        .name("经度")
        .onChange(() => this.updateBoat());
      this.gui
        .add(this.boatParams, "latitude", -90, 90)
        .name("纬度")
        .onChange(() => this.updateBoat());
      this.gui
        .add(this.boatParams, "height", 0, 100000)
        .name("高度")
        .onChange(() => this.updateBoat());
      this.gui
        .add(this.boatParams, "heading", -180, 180)
        .name("偏航角")
        .onChange(() => this.updateBoat());
      this.gui
        .add(this.boatParams, "pitch", -90, 90)
        .name("俯仰角")
        .onChange(() => this.updateBoat());
      this.gui
        .add(this.boatParams, "roll", -180, 180)
        .name("翻滚角")
        .onChange(() => this.updateBoat());
    },
    updateBeam(satellitePosition, color, beamEntity) {
      const boatPosition = this.boatEntity.position.getValue(
        this.viewer.clock.currentTime
      );
      const direction = Cesium.Cartesian3.subtract(
        satellitePosition,
        boatPosition,
        new Cesium.Cartesian3()
      );
      Cesium.Cartesian3.normalize(direction, direction);

      const baseWidth = 50000; // 正方形的宽度
      const baseHeight = baseWidth; // 高度与宽度相同，确保是正方形

      // 计算四个顶点，确保形成一个正方形
      const right = Cesium.Cartesian3.cross(
        direction,
        new Cesium.Cartesian3(0, 0, 1),
        new Cesium.Cartesian3()
      );
      Cesium.Cartesian3.normalize(right, right);

      const up = Cesium.Cartesian3.cross(
        right,
        direction,
        new Cesium.Cartesian3()
      );
      Cesium.Cartesian3.normalize(up, up);

      const halfWidth = baseWidth / 2;
      const halfHeight = baseHeight / 2;

      const bottomLeft = Cesium.Cartesian3.add(
        satellitePosition,
        Cesium.Cartesian3.multiplyByScalar(
          right,
          -halfWidth,
          new Cesium.Cartesian3()
        ),
        new Cesium.Cartesian3()
      );
      const bottomRight = Cesium.Cartesian3.add(
        satellitePosition,
        Cesium.Cartesian3.multiplyByScalar(
          right,
          halfWidth,
          new Cesium.Cartesian3()
        ),
        new Cesium.Cartesian3()
      );
      const topRight = Cesium.Cartesian3.add(
        satellitePosition,
        Cesium.Cartesian3.multiplyByScalar(
          right,
          halfWidth,
          new Cesium.Cartesian3()
        ),
        new Cesium.Cartesian3()
      );
      const topLeft = Cesium.Cartesian3.add(
        satellitePosition,
        Cesium.Cartesian3.multiplyByScalar(
          right,
          -halfWidth,
          new Cesium.Cartesian3()
        ),
        new Cesium.Cartesian3()
      );

      Cesium.Cartesian3.add(
        bottomLeft,
        Cesium.Cartesian3.multiplyByScalar(
          up,
          -halfHeight,
          new Cesium.Cartesian3()
        ),
        bottomLeft
      );

      Cesium.Cartesian3.add(
        bottomRight,
        Cesium.Cartesian3.multiplyByScalar(
          up,
          -halfHeight,
          new Cesium.Cartesian3()
        ),
        bottomRight
      );

      Cesium.Cartesian3.add(
        topRight,
        Cesium.Cartesian3.multiplyByScalar(
          up,
          halfHeight,
          new Cesium.Cartesian3()
        ),
        topRight
      );

      Cesium.Cartesian3.add(
        topLeft,
        Cesium.Cartesian3.multiplyByScalar(
          up,
          halfHeight,
          new Cesium.Cartesian3()
        ),
        topLeft
      );

      const basePoints = [bottomLeft, bottomRight, topRight, topLeft];

      // 更新底面实体
      beamEntity.baseEntity.polygon.hierarchy = new Cesium.CallbackProperty(
        () => {
          return new Cesium.PolygonHierarchy(basePoints);
        },
        false
      );

      // 更新侧面实体
      beamEntity.sideEntities[0].polygon.hierarchy =
        new Cesium.CallbackProperty(
          () =>
            new Cesium.PolygonHierarchy([
              boatPosition,
              bottomLeft,
              bottomRight,
            ]),
          false
        );
      beamEntity.sideEntities[1].polygon.hierarchy =
        new Cesium.CallbackProperty(
          () =>
            new Cesium.PolygonHierarchy([boatPosition, bottomRight, topRight]),
          false
        );
      beamEntity.sideEntities[2].polygon.hierarchy =
        new Cesium.CallbackProperty(
          () => new Cesium.PolygonHierarchy([boatPosition, topRight, topLeft]),
          false
        );
      beamEntity.sideEntities[3].polygon.hierarchy =
        new Cesium.CallbackProperty(
          () =>
            new Cesium.PolygonHierarchy([boatPosition, topLeft, bottomLeft]),
          false
        );
    },

    updateYellowBeam(satellitePosition) {
      this.updateBeam(
        satellitePosition,
        Cesium.Color.BLUE,
        this.beamEntities[0]
      );
    },

    updateRedBeam(satellitePosition) {
      this.updateBeam(
        satellitePosition,
        Cesium.Color.RED,
        this.redBeamEntities[0]
      );
    },

    updateBoat() {
      if (this.boatEntity) {
        const position = Cesium.Cartesian3.fromDegrees(
          this.boatParams.longitude,
          this.boatParams.latitude,
          this.boatParams.height
        );
        const hpr = new Cesium.HeadingPitchRoll(
          Cesium.Math.toRadians(this.boatParams.heading),
          Cesium.Math.toRadians(this.boatParams.pitch),
          Cesium.Math.toRadians(this.boatParams.roll)
        );
        const orientation = Cesium.Transforms.headingPitchRollQuaternion(
          position,
          hpr
        );

        this.boatEntity.position = position;
        this.boatEntity.orientation = orientation;
      }
    },

    locateView() {
      this.createBoatModel("/model/boat.glb", this.boatParams.height);
      this.initGUI();
      this.viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(104, 28.8, 1500000),
        orientation: {
          heading: Cesium.Math.toRadians(81.4),
          pitch: Cesium.Math.toRadians(-37.3),
          roll: 0.07,
        },
        duration: 3,
        easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT,
      });
      // 监听相机位置变化并输出经纬度和高度
      // this.viewer.camera.changed.addEventListener(() => {
      //     const cartographic = Cesium.Cartographic.fromCartesian(this.viewer.camera.position);
      //     const longitude = Cesium.Math.toDegrees(cartographic.longitude);
      //     const latitude = Cesium.Math.toDegrees(cartographic.latitude);
      //     const height = cartographic.height;
      //     // 获取相机的朝向（heading、pitch、roll）
      //     const heading = Cesium.Math.toDegrees(this.viewer.camera.heading);
      //     const pitch = Cesium.Math.toDegrees(this.viewer.camera.pitch);
      //     const roll = Cesium.Math.toDegrees(this.viewer.camera.roll);

      //     // 打印结果
      //     console.log(`经度: ${longitude}, 纬度: ${latitude}, 高度: ${height}`);
      //     console.log(`朝向 - 偏航角 (heading): ${heading}, 俯仰角 (pitch): ${pitch}, 翻滚角 (roll): ${roll}`);
      // });

      this.intervalId = setInterval(() => {
        // 获取可见范围内的卫星
        const visibleSatellites = this.satelliteEntities.filter((entity) => {
          const satellitePosition = entity.position.getValue(
            this.viewer.clock.currentTime
          );
          const boatPosition = this.boatEntity.position.getValue(
            this.viewer.clock.currentTime
          );
          const distance = Cesium.Cartesian3.distance(
            satellitePosition,
            boatPosition
          );
          return distance <= this.visibilityRange;
        });

        // 隐藏不可见卫星的轨迹，显示可见卫星的轨迹
        this.satelliteEntities.forEach((entity) => {
          if (entity.path) {
            entity.path.show = visibleSatellites.includes(entity); // 仅显示可见卫星的轨迹
          }
        });

        if (visibleSatellites.length > 0) {
          // 循环选择卫星
          if (this.currentSatelliteIndex >= visibleSatellites.length) {
            this.currentSatelliteIndex = 0;
          }
          const currentSatellite =
            visibleSatellites[this.currentSatelliteIndex];
          const satellitePosition = currentSatellite.position.getValue(
            this.viewer.clock.currentTime
          );

          // 更新黄色波束
          this.updateYellowBeam(satellitePosition);

          // 更新红色波束（指向第一颗卫星）
          this.updateRedBeam(
            visibleSatellites[0].position.getValue(
              this.viewer.clock.currentTime
            )
          );

          this.currentSatelliteIndex++;
        } else {
          // 隐藏波束
          this.beamEntities[0].baseEntity.show = false;
          this.redBeamEntities[0].baseEntity.show = false;
          this.beamEntities[0].sideEntities.forEach(
            (entity) => (entity.show = false)
          );
          this.redBeamEntities[0].sideEntities.forEach(
            (entity) => (entity.show = false)
          );
        }
      }, this.timer);
    },

    clearYellowBeams() {
      this.beamEntities[0].baseEntity.show = false;
      this.beamEntities[0].sideEntities.forEach(
        (entity) => (entity.show = false)
      );
    },

    clearRedBeams() {
      this.redBeamEntities[0].baseEntity.show = false;
      this.redBeamEntities[0].sideEntities.forEach(
        (entity) => (entity.show = false)
      );
    },

    createBoatModel(url, height) {
      const position = Cesium.Cartesian3.fromDegrees(
        this.boatParams.longitude,
        this.boatParams.latitude,
        height
      );
      const hpr = new Cesium.HeadingPitchRoll(
        Cesium.Math.toRadians(this.boatParams.heading),
        Cesium.Math.toRadians(this.boatParams.pitch),
        Cesium.Math.toRadians(this.boatParams.roll)
      );
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        position,
        hpr
      );

      this.boatEntity = this.viewer.entities.add({
        name: "Boat",
        position: position,
        orientation: orientation,
        model: {
          uri: url,
          minimumPixelSize: 128,
          maximumScale: 200000,
        },
        description: `船只信息`,
      });
    },

    loadSatellites() {
      if (this.viewer) {
        // 清除所有已有的数据源
        this.viewer.dataSources.removeAll();

        // 加载新的 CZML 文件
        this.viewer.dataSources
          .add(Cesium.CzmlDataSource.load("czml/qianfan.czml"))
          .then((dataSource) => {
            this.satelliteEntities = dataSource.entities.values;

            const customColor = new Cesium.Color(0, 255, 0); // 浅绿色，完全不透明
            // 遍历所有实体
            this.satelliteEntities.forEach((entity) => {
              // 检查实体是否有 path 属性
              if (entity.path) {
                // 修改 path 的颜色
                entity.path.material = new Cesium.ColorMaterialProperty(
                  customColor
                );
                entity.path.width = 1; // 设置宽度
              }
            });
            // 设置时钟参数
            this.viewer.clock.shouldAnimate = true;
            this.viewer.clock.multiplier = 1;
            const startTime = Cesium.JulianDate.fromIso8601(
              "2025-03-04T10:06:50Z"
            );
            this.viewer.clock.startTime = startTime;
            this.viewer.clock.currentTime = startTime;
          });
      }
    },
  },
};
</script>

<style scoped>
#CesiumContainer {
  height: 100vh;
  width: 100%;
  position: relative;
}

.button {
  position: absolute;
  z-index: 100;
  top: 20px;
  left: 20px;
  background: rgba(0, 0, 0, 0.7);
  padding: 10px;
  border-radius: 5px;
}

/* 波束辉光效果 */
.cesium-sensor-volume {
  filter: drop-shadow(0 0 8px rgba(0, 255, 255, 0.5));
}

/* 隐藏Cesium logo */
.cesium-widget-credits {
  display: none !important;
}
</style>